package cheme.ProcessEditor.Figures.Util;

import org.eclipse.draw2d.AbstractLocator;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;

public class TagLocator extends AbstractLocator
{
	/** The start (or source) of the Connection */
	public static final int SOURCE = 2;

	/** The end (or target) of the Connection */
	public static final int TARGET = 3;

	/** The middle of the Connection */
	public static final int MIDDLE = 4;

	private Connection connection;

	private int alignment;
	
	private int xGap = 0;
	private int yGap = 0;

	public int getXGap()
	{
		return xGap;
	}

	public void setXGap(int gap)
	{
		xGap = gap;
	}

	public int getYGap()
	{
		return yGap;
	}

	public void setYGap(int gap)
	{
		yGap = gap;
	}

	public TagLocator(Connection connection)
	{
		this(connection, MIDDLE, 0, 10);
	}
	
	public TagLocator(Connection connection, int align)
	{
		this(connection, align, 0, 10);
	}

	public TagLocator(Connection connection, int align, int xOffset, int yOffset)
	{
		setConnection(connection);
		setAlignment(align);
		setXGap(0);
		setYGap(10);
	}

	public int getAlignment()
	{
		return alignment;
	}

	public final Connection getConnection()
	{
		return connection;
	}

	protected Point getReferencePoint()
	{
		Point p = getLocation(getConnection().getPoints());
		getConnection().translateToAbsolute(p);
		return p;
	}

	protected Point getLocation(PointList points)
	{
		switch (getAlignment())
		{
		case SOURCE:
			return points.getPoint(Point.SINGLETON, 0);
		case TARGET:
			return points.getPoint(Point.SINGLETON, points.size() - 1);
		case MIDDLE:
			if(points.size() % 2 == 0)
			{
				int i = points.size() / 2;
				int j = i - 1;
				Point p1 = points.getPoint(j);
				Point p2 = points.getPoint(i);
				Dimension d = p2.getDifference(p1);
				return Point.SINGLETON.setLocation(p1.x + d.width / 2, p1.y + d.height / 2);
			}
			int i = (points.size() - 1) / 2;
			return points.getPoint(Point.SINGLETON, i);
		default:
			return new Point();
		}
	}

	protected void setAlignment(int align)
	{
		alignment = align;
	}

	protected void setConnection(Connection connection)
	{
		this.connection = connection;
	}
	
	public void relocate(IFigure target)
	{
		Dimension prefSize = target.getPreferredSize();
		Point center = getReferencePoint();
		target.translateToRelative(center);
		target.setBounds(getNewBounds(prefSize, center));
	}
	
	protected Rectangle getNewBounds(Dimension size, Point center)
	{
		Rectangle bounds = new Rectangle(center, size);

		bounds.x -= bounds.width / 2;
		bounds.y -= bounds.height / 2;
		
		bounds.x += getXGap();
		bounds.y += (bounds.height / 2)  + getYGap();

		return bounds;
	}
}
